#region Copyright
//	Copyright (c) 2007 eBay, Inc.
//
//	This program is licensed under the terms of the eBay Common Development and 
//	Distribution License (CDDL) Version 1.0 (the "License") and any subsequent 
//	version thereof released by eBay.  The then-current version of the License 
//	can be found at https://www.codebase.ebay.com/Licenses.html and in the 
//	eBaySDKLicense file that is under the eBay SDK install directory.
#endregion

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Collections;
using System.Collections.Specialized;
using System.Threading;
using System.Configuration;
using eBay.Service.Core.Sdk;
using eBay.Service.Core.Soap;
using eBay.Service.Util;
using System.Windows.Forms;


namespace GetItemTester
{
	/// <summary>
	/// Summary description for ItemFetcher.
	/// </summary>
	public class ItemFetcher
	{
		#region private fields

		private Form1 app;
		private System.Collections.Specialized.StringCollection itemIDs;
		private int indexItemIDs = 0;
		private Mutex mItemIDs = new Mutex();
		private int numThreads;
		private int numCallsPerThread;
		private int numCalls;
		private string token;
		private ArrayList threads = new ArrayList();
		private bool stop = false;
		private static ApiLogger logger = new FileLogger(ConfigurationSettings.AppSettings.Get("logfile"));
		private CallMetricsTable mMetrics = new CallMetricsTable();
		private TextBox txtLogger;
        private bool rampUp = false;
		//this delegate enables asynchronous call for setting
		//the message to the textBox on the form
		private delegate void setMessageCallBack(string message);

        private IList<KeyValuePair<string, string>> listingImages = new List<KeyValuePair<string, string>>();
		#endregion

		#region constructor

		/// <summary>
		/// 
		/// </summary>
		/// <param name="app"></param>
		/// <param name="txtLogger">a TextBox show message</param>
		/// <param name="numThreads">specify how many threads to be tested</param>
		/// <param name="numCalls">specify how many methods will be called for each thread</param>
		/// <param name="token"></param>
        public ItemFetcher(Form1 app, TextBox txtLogger, int numThreads, string ebayUser, string token, bool rampUp, IList<KeyValuePair<string, string>> listingImages) 
		{
			this.app = app;
			
            this.listingImages = listingImages;
            if(numThreads>listingImages.Count)
            {
                this.numThreads = listingImages.Count;
            }
            else
            {
                this.numThreads = numThreads;
            }
		    this.numCalls = listingImages.Count;
            if (numCalls % this.numThreads==0)
            {
                this.numCallsPerThread = numCalls / this.numThreads ;

            }
            else
            {
                this.numCallsPerThread = numCalls / this.numThreads + 1;

            }
           
			this.token = token;
			this.txtLogger=txtLogger;
            this.rampUp = rampUp;


			eBayApi.Init(app,ebayUser, token, logger);
			eBayApi.log("total calls: " + this.numCalls);

            for (int i = 0; i < this.numThreads; i++) 
			{
				//specify the handler to the thread
				ThreadStart ts = new ThreadStart(entryHandler);

				Thread thread = new Thread(ts);
				thread.Name = i.ToString();
                
				threads.Add(thread);
			}
		}

		#endregion

		#region Event

        public delegate void FetchCompleteDelegate(object sender, EventArgs e);
        public delegate void UploadSiteHostePicturesCompleteDelegate(object sender, UploadSitedHostedPicturesEventArgs e);

		public event FetchCompleteDelegate FetchCompleteEvent;
        public event UploadSiteHostePicturesCompleteDelegate UploadSiteHostePicturesCompleteEvent;

		#endregion

		#region public method

		/// <summary>
		/// all threads start executing 
		/// </summary>
		public void Start() 
		{
			foreach (Thread thread in threads) 
			{
				thread.Start();
			}
		}

		/// <summary>
		/// all threads stop executing
		/// </summary>
		public void Stop() 
		{
			stop = true;
			foreach (Thread thread in threads) 
			{
				if (thread.IsAlive)
					thread.Join(5000);
			}
		}

		#endregion

		#region private method

		/// <summary>
		/// entry handler for the thread
		/// </summary>
		private void entryHandler() 
		{
			string newEPSUrl;
		
			string threadname = Thread.CurrentThread.Name;

		    int threadNumber = Convert.ToInt16(threadname);
		    int calcultedNumCallsPerThread = threadNumber == numThreads-1
		                                         ? numCalls - numCallsPerThread*threadNumber
		                                         : numCallsPerThread;
                ;
			for(int i = 0; i< calcultedNumCallsPerThread; i++)
			{
				if(this.stop)
				{
					break;
				}
			    KeyValuePair<string,string> item = listingImages[(threadNumber)*numCallsPerThread + i];
                newEPSUrl = eBayApi.UploadPictures(item);
                //sleep one second
                Thread.Sleep(1000);
				//add an item and log all processing message
                string message = String.Format("Thread: {0} ,Begin uploading an item {1}...", threadname, item.Value);
				logMessage(message);

             
                if (!string.IsNullOrEmpty(newEPSUrl))
				{
                    message = String.Format("Thread: {0} ,Upload item {1} success: {2}", threadname, item.Value, newEPSUrl);
				}
				else
				{
                    message = String.Format("Thread: {0} ,Upload item {1} failure.", threadname, item.Value);
				}
				logMessage(message);
			    item = new KeyValuePair<string, string>(item.Key,newEPSUrl);
                if (UploadSiteHostePicturesCompleteEvent != null)
                    UploadSiteHostePicturesCompleteEvent(this, new UploadSitedHostedPicturesEventArgs(item));

				if (Interlocked.Decrement(ref numCalls) == 0) 
				{
					//mMetrics.GenerateReport(logger);
					if (FetchCompleteEvent != null)
                        FetchCompleteEvent(this, new EventArgs());
				}
			}//close for loop
			
		}//close GetItemHandler method



		/// <summary>
		/// log message
		/// </summary>
		/// <param name="message"></param>
		private void logMessage(string message)
		{
            if (txtLogger.InvokeRequired)
            {
                //it is on the different thread, so use the Invoke method
                setMessageCallBack d = new setMessageCallBack(logMessageCallBack);
                app.Invoke(d, new object[] { message });
            }
            else
            {
                logMessageCallBack(message);
            }
		}


		/// <summary>
		/// 
		/// </summary>
		/// <param name="message"></param>
		private void logMessageCallBack(string message)
		{
			string msg=String.Format("{0}\t{1}",DateTime.Now.ToString(),message);
			eBayApi.log(String.Format("{0}{1}",msg,System.Environment.NewLine));

			txtLogger.Text=String.Format("{0}{1}{2}",msg,System.Environment.NewLine,txtLogger.Text);
		}

		#endregion

	}


    public class UploadSitedHostedPicturesEventArgs :EventArgs
    {
        private KeyValuePair<string, string> _pair;
        public KeyValuePair<string, string> Item
        {
            get { return _pair; }
        }
        public UploadSitedHostedPicturesEventArgs(KeyValuePair<string,string> pair)
        {
            _pair = pair;
        }
    }

    public class ImageItem
    {
        private string _epsUrl;
        public string EPSUrl
        {
            get { return _epsUrl; }
            set { _epsUrl = value; }
        }

        private string _productCode;
        public string ProductCode
        {
            get { return _productCode; }
            set { _productCode = value; }
        }
    }
}
